Technical Q&A QA1251
FSSetCatalogInfo vs UID and GID


Q: FSSetCatalogInfo を使用して、ファイルの UID と GID を変更するにはどうすればよいでしょうか?

A: アップルは、既存のソースコードとの互換性を向上させるために、FSSetCatalogInfo に渡される UID と GID の値を無視するようにしました。大部分のアプリケーションのコードは、コピー元で FSGetCatalogInfo を呼び出し、次にコピー先で FSSetCatalogInfo を呼び出すことによって、ファイルのメタデータをコピーします。しかし、Mac OS X では、root 以外のプログラムは、ファイルの UID を変更できないようになっています。このため、FSSetCatalogInfo が明示的に実装されている場合に、この標準的なコピーアルゴリズムを使って自分が所有者ではないファイルをコピーすると、パーミッションエラーが発生してプログラムの処理は失敗します。

現時点では、Carbon File Manager を使用してファイルの UID または GID を設定する方法がありません。推奨される回避策としては、リスト 1 に示すように、BSD を使用して chown を呼び出す方法があります。


リスト 1 UID と GID を設定する FSSetCatalogInfo の一例

#include <CoreServices/CoreServices.h>
#include <sys/param.h>
#include <unistd.h>

static OSStatus FSSetCatalogInfoIDs(const FSRef *ref, 
                                    FSCatalogInfoBitmap whichInfo, 
                                    const FSCatalogInfo *catalogInfo)
  // kFSCatInfoPermissions フラグを渡す場合に FUID と FGID 
  // を実際に設定しようとする FSSetCatalogInfo の一例。これは、
  // <rdar://problem/2631025> のための回避策として
  // 現在推奨されている。userID または groupID の値として -1
  // を渡すことにより、値の変更を希望しないことを指定できる。
{
    OSStatus                    err;
    const FSPermissionInfo *    permInfo;
    uid_t                       uid;
    gid_t                       gid;
    
    err = FSSetCatalogInfo(ref, whichInfo, catalogInfo);
    if ( (err == noErr) && (whichInfo & kFSCatInfoPermissions) ) {
        permInfo = (const FSPermissionInfo *) catalogInfo->permissions;
        uid = (uid_t) permInfo->userID;
        gid = (gid_t) permInfo->groupID;
        if (uid != -1 || gid != -1 ) {
            char filePath[MAXPATHLEN];
            
            err = FSRefMakePath(ref, (UInt8 *) filePath, sizeof(filePath));
            if (err == noErr) {
                err = chown(filePath, uid, gid);
                if (err == -1) {
                    err = errno;
                }
            }
        }
    }
return err;
}

重要:
上記のコードによって、特別な権限が与えられるわけではありません。許可されていない操作を実行しようとすると(ターミナルで man 2 chown を入力して確認してください)、エラーが発生して FSSetCatalogInfoIDs は失敗します。追加の権限を取得する方法についての詳細は、Authorization Services のドキュメントを参照してください。

注記:
ファイルシステムオブジェクトをコピーする自作のコードを記述しているためにこの問題を発見した場合は、代わりに、DTS のサンプルコード FSCopyObjects のコードの使用を検討するとよいかもしれません。


[2003 年 3 月 26 日]